
import * as mars3d from "mars3d"
import * as GeoTIFF from "geotiff"
import * as plotty from "plotty"
import { handleMinioUrl } from "@mars/utils/minio"
import * as turf from "@turf/turf"
const noisePath: string = import.meta.env.VITE_APP_NOISE_PATH as string

let map: mars3d.Map // 地图对象
const Cesium = mars3d.Cesium
let _last_basemap: string | number | mars3d.layer.BaseTileLayer
// 叠加的图层
let graphicLayer: mars3d.layer.GraphicLayer // 矢量图层

// 初始化当前业务
export function onMounted(mapInstance: mars3d.Map): void {
  map = mapInstance // 记录map

  map.setCameraView({ lat: 31.643162, lng: 120.74399, alt: 25593.9, heading: 359.9, pitch: -90 })
  
  // addTileLayer()

}

// 释放当前业务
export function onUnmounted(): void {
  if (graphicLayer) {
    graphicLayer.clear()
    map.removeLayer(graphicLayer, true)
    graphicLayer = null
  }
  layerManager.removeCurrentLayer()
  map = null
}


// 图层管理对象
export const layerManager = {
  currentLayer: null as mars3d.layer.ImageLayer | null,
  
  /**
   * 添加并显示TIF图层
   * @param originalData 图层数据或URL
   * @param options 配置选项
   */
  async addTileLayer(originalData: string, options: {
    cropWithGeoJSON?: string;
    colorMap?: (value: number) => number[];
    flyTo?: boolean;
  } = {}) {
    this.removeCurrentLayer()
    
    try {
      // 1. 准备图层URL
      const originalUrl = this.prepareLayerUrl(originalData)
      
      // 2. 获取图像数据
      const result = options.cropWithGeoJSON 
        ? await this.cropTifWithGeoJSON(originalUrl, options.cropWithGeoJSON)
        : await this.tifToImage(originalUrl, options.colorMap)
      
      if (!result?.image || !result.extent) {
        throw new Error("获取图像数据失败")
      }

      // 3. 创建并添加图层
      this.currentLayer = new mars3d.layer.ImageLayer({
        name: "动态地图图层",
        url: result.image,
        rectangle: this.adjustExtent(result.extent), // 边缘调整
        crs: result.crs as mars3d.CRS,
        flyTo: options.flyTo ?? true,
        alpha: 0.9 // 添加透明度
      })

      map.addLayer(this.currentLayer)
      
      // 4. 添加边缘遮罩
      // if (options.cropWithGeoJSON) {
      //   this.addCropMask(options.cropWithGeoJSON)
      // }
      
    } catch (error) {
      console.error("图层加载失败:", error)
      throw error
    }
  },
  
  /**
   * 移除当前图层
   */
  removeCurrentLayer() {
    if (this.currentLayer) {
      map.removeLayer(this.currentLayer)
      this.currentLayer = null
      this.removeCropMask()
    }
  },
  
  /**
   * 准备图层URL
   */
  prepareLayerUrl(data: string): string {
    // 这里可以添加URL处理逻辑
    return data.startsWith("http") || data.startsWith("https") ? data : handleMinioUrl(noisePath + data + ".tif")
  },
  
  /**
   * 调整范围边界
   */
  adjustExtent(extent: { xmin: number; ymin: number; xmax: number; ymax: number }) {
    // 添加1%的边界缓冲
    const buffer = 0.01
    const width = extent.xmax - extent.xmin
    const height = extent.ymax - extent.ymin
    
    return {
      xmin: extent.xmin - width * buffer,
      ymin: extent.ymin - height * buffer,
      xmax: extent.xmax + width * buffer,
      ymax: extent.ymax + height * buffer
    }
  },
  
  /**
   * 添加裁剪遮罩
   */
  async addCropMask(geojsonUrl: string) {
    try {
      const geojson = await mars3d.Util.fetchJson({ url: geojsonUrl })
      map.addLayer(new mars3d.layer.GeoJsonLayer({
        name: "裁剪遮罩",
        data: geojson,
        symbol: {
          type: "polygon",
          styleOptions: {
            color: "#000",
            opacity: 0,
            outline: false,
            outlineColor: "#fff",
            outlineWidth: 0
          }
        },
        flyTo: false
      }))
    } catch (error) {
      console.warn("无法添加裁剪遮罩:", error)
    }
  },
  
  /**
   * 移除裁剪遮罩
   */
  removeCropMask() {
    const maskLayer = map.getLayer("裁剪遮罩")
    if (maskLayer) {
      map.removeLayer(maskLayer)
    }
  },
  
  /**
   * TIF转图像
   */
  async tifToImage(url: string, colorMap?: (value: number) => number[]) {
    const tif = await GeoTIFF.fromUrl(url)
    const image = await tif.getImage()
    const [red] = await image.readRasters() // 只读取红色通道
    
    const canvas = mars3d.DomUtil.create("canvas")
    canvas.width = image.getWidth()
    canvas.height = image.getHeight()
    const ctx = canvas.getContext("2d")
    const imageData = ctx.createImageData(canvas.width, canvas.height)
    
    // 使用默认或自定义颜色映射
    const getColor = colorMap || this.defaultColorMap
    
    for (let i = 0; i < imageData.data.length / 4; i++) {
      const color = getColor(red[i])
      imageData.data.set(color, i * 4)
      imageData.data[i * 4 + 3] = 255 // Alpha通道
    }
    
    ctx.putImageData(imageData, 0, 0)
    
    // 处理坐标范围和CRS
    const [xmin, ymin, xmax, ymax] = image.getBoundingBox()
    const code = image.geoKeys.ProjectedCSTypeGeoKey || image.geoKeys.GeographicTypeGeoKey
    const crs = "EPSG:" + code
    
    return {
      image: canvas.toDataURL("image/png"),
      extent: { xmin, ymin, xmax, ymax },
      crs
    }
  },
  
  /**
   * 默认颜色映射
   */
  defaultColorMap(value: number): number[] {
    if (value >= 110) { return [199, 21, 133] } // #C71585
    if (value >= 90) { return [255, 0, 0] } // #FF0000
    if (value >= 70) { return [255, 120, 0] } // #FF7800
    if (value >= 50) { return [250, 212, 0] } // #FAD400
    if (value >= 30) { return [199, 249, 83] } // #C7F953
    return [0, 255, 81] // #00FF51
  },
  
    /**
     * 使用GeoJSON裁剪TIF
     */
  async  cropTifWithGeoJSON(url: string, geojsonUrl: string, colorMap?: (value: number) => number[]): Promise<any> {
    // 1. 获取并解析GeoJSON数据
    let geometry
    try {
      const geojson = await mars3d.Util.fetchJson({ url: geojsonUrl })
      
      // 更健壮的geometry提取逻辑
      if (!geojson || !geojson.type) {
        throw new Error("无效的GeoJSON数据")
      }

      if (geojson.type === "FeatureCollection") {
        if (!geojson.features || geojson.features.length === 0) {
          throw new Error("FeatureCollection中未包含任何要素")
        }
        geometry = geojson.features[0].geometry
      } else if (geojson.type === "Feature") {
        geometry = geojson.geometry
      } else if (geojson.type === "GeometryCollection") {
        throw new Error("暂不支持GeometryCollection类型")
      } else {
        geometry = geojson
      }
    } catch (error) {
      throw new Error(`获取或解析GeoJSON失败: ${error}`)
    }

    // 验证几何类型
    if (!geometry || !["Polygon", "MultiPolygon"].includes(geometry.type)) {
      throw new Error("只支持Polygon或MultiPolygon类型的GeoJSON")
    }

    // 2. 加载TIF文件
    const tif = await GeoTIFF.fromUrl(url)
    const image = await tif.getImage()
    const [imageMinX, imageMinY, imageMaxX, imageMaxY] = image.getBoundingBox()
    const imageWidth = image.getWidth()
    const imageHeight = image.getHeight()

    // 3. 计算精确裁剪边界
    const geojsonBbox = turf.bbox(geometry)
    let [minX, minY, maxX, maxY] = geojsonBbox
    
    // 边界安全处理
    minX = Math.max(minX, imageMinX)
    minY = Math.max(minY, imageMinY)
    maxX = Math.min(maxX, imageMaxX)
    maxY = Math.min(maxY, imageMaxY)

    // 4. 计算像素范围 (添加1像素缓冲避免边缘问题)
    const pixelLeft = Math.max(0, Math.floor((minX - imageMinX) / (imageMaxX - imageMinX) * imageWidth) - 1)
    const pixelTop = Math.max(0, Math.floor((imageMaxY - maxY) / (imageMaxY - imageMinY) * imageHeight) - 1)
    const pixelRight = Math.min(imageWidth, Math.ceil((maxX - imageMinX) / (imageMaxX - imageMinX) * imageWidth) + 1)
    const pixelBottom = Math.min(imageHeight, Math.ceil((imageMaxY - minY) / (imageMaxY - imageMinY) * imageHeight) + 1)

    const cropWidth = pixelRight - pixelLeft
    const cropHeight = pixelBottom - pixelTop

    if (cropWidth <= 0 || cropHeight <= 0) {
      throw new Error("裁剪区域无效")
    }

    // 5. 分块读取栅格数据 (避免内存溢出)
    const rasters: any = await image.readRasters({
      window: [pixelLeft, pixelTop, pixelRight, pixelBottom],
      width: cropWidth,
      height: cropHeight,
      interleave: true // 获取交错排列的RGB数据
    })

    // 6. 创建Canvas
    const canvas = document.createElement("canvas")
    canvas.width = cropWidth
    canvas.height = cropHeight
    const ctx = canvas.getContext("2d", { willReadFrequently: true })
    if (!ctx) { throw new Error("无法获取Canvas上下文") }

    // 7. 创建并填充图像数据
    const imageData = ctx.createImageData(cropWidth, cropHeight)
    const coords = geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates

    // 预计算所有多边形路径
    const paths = coords.map((polygon: any[][]) => {
      return polygon.map((ring: any[]) => {
        return ring.map(([x, y]: [number, number]) => {
          const px = ((x - imageMinX) / (imageMaxX - imageMinX) * imageWidth) - pixelLeft
          const py = ((imageMaxY - y) / (imageMaxY - imageMinY) * imageHeight) - pixelTop
          return [px, py] as [number, number]
        })
      })
    })

    // 8. 填充像素数据
  
    const getColor = colorMap || this.defaultColorMap
  
    // 9. 统一像素处理方式
    const rasterData = await image.readRasters({
      window: [pixelLeft, pixelTop, pixelRight, pixelBottom],
      width: cropWidth,
      height: cropHeight
    })

    // 获取单通道数据（与tifToImage保持一致）
    const values = Array.isArray(rasters) ? rasters[0] : rasters

    // 创建透明背景
    
    for (let y = 0; y < cropHeight; y++) {
      for (let x = 0; x < cropWidth; x++) {
        const i = y * cropWidth + x
        const pixelIndex = i * 4
        const pixelPos: [number, number] = [x + 0.5, y + 0.5]

        // 检查是否在裁剪区域内
        const isInside = paths.some(polygon => 
          polygon.some(ring => isPointInRing(pixelPos, ring))
        )

        if (isInside) {
          // 统一使用单通道值+颜色映射（与tifToImage相同逻辑）
          const value = values[i]
          const [r, g, b] = getColor(value)
          
          imageData.data[pixelIndex] = r
          imageData.data[pixelIndex + 1] = g
          imageData.data[pixelIndex + 2] = b
          imageData.data[pixelIndex + 3] = 255
        } else {
          // 区域外透明处理
          imageData.data[pixelIndex + 3] = 0
        }
      }
    }

    // 10. 统一输出格式
    ctx.putImageData(imageData, 0, 0)

    return {
      image: canvas.toDataURL("image/png"),
      extent: { xmin: minX, ymin: minY, xmax: maxX, ymax: maxY },
      crs: "EPSG:" + (image.geoKeys?.ProjectedCSTypeGeoKey || image.geoKeys?.GeographicTypeGeoKey || "4326"),
      transparent: true // 明确标记为透明
    }
  }
}


// 高性能的点在多边形内检测 (射线法)
function isPointInRing(point: [number, number], ring: [number, number][]): boolean {
  let inside = false
  const [x, y] = point
  
  for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
    const [xi, yi] = ring[i]
    const [xj, yj] = ring[j]
    
    const intersect = ((yi > y) !== (yj > y)) &&
      (x < (xj - xi) * (y - yi) / (yj - yi) + xi)
    if (intersect) { inside = !inside }
  }
  
  return inside
}

